package org.lex.net.ftp;

import java.net.MalformedURLException;
import java.net.URL;

import org.lex.io.filesystem.FileNameUtilities;
import org.lex.net.Password;


/**
 * This class is designed to be immutable
 */
public final class FTPURL {
	public static final String PROTOCOL = "ftp";
	public static final int DEFAULT_PORT = 21;
	public static final String DEFAULT_PATH = "/";
	public static final FTPURL FAKE_URL = new FTPURL();
	// ==========================================
	private String host = "localhost";
	private int port = DEFAULT_PORT;
	private String path = DEFAULT_PATH;
	private Password auth = Password.ANONYMOUS;

	public static FTPURL parseFtpUrl(String str) {
		if (null == str || 0 == str.trim().length())
			return null;
		try {
			URL url = new URL(str.trim());
			Password pass = Password.ANONYMOUS;
			String userInfo = url.getUserInfo();
			if (null != userInfo && false == userInfo.isEmpty()) {
				int index = userInfo.indexOf(':');
				if (-1 != index) {
					String username = userInfo.substring(0, index);
					String password = userInfo.substring(index + 1);
					pass = new Password(username, password.toCharArray());
				}
			}
			int port = url.getPort();
			if (-1 == port)
				port = url.getDefaultPort();
			FTPURL ftpUrl = new FTPURL();
			ftpUrl.host = url.getHost();
			ftpUrl.port = port;
			ftpUrl.auth = pass;
			ftpUrl.path = url.getPath();
			return ftpUrl;
		} catch (MalformedURLException e) {
			return null;
		}
	}

	private FTPURL() {
	}

	public FTPURL(String host) {
		this(host, DEFAULT_PORT);
	}

	public FTPURL(String host, int port) {
		this(Password.ANONYMOUS, host, port);
	}

	public FTPURL(Password auth, String host) {
		this(auth, host, DEFAULT_PORT, DEFAULT_PATH);
	}

	public FTPURL(Password auth, String host, int port) {
		this(auth, host, port, DEFAULT_PATH);
	}

	public FTPURL(Password auth, String host, int port, String path) {
		this.host = host;
		this.auth = auth;
		this.port = port;
		this.path = path;
	}

	public boolean isAnonymous() {
		return "anonymous".equals(auth.getUserName());
	}

	/**
	 * return ftp://USER:******@HOST:PORT/
	 */
	public String getServer() {
		return this.getServer(false);
	}

	public String getServer(boolean showPassword) {
		StringBuilder buf = new StringBuilder(PROTOCOL);
		buf.append("://");
		buf.append(auth.getUserName()).append(':');
		if (showPassword)
			buf.append(this.auth.getPassword());
		else
			buf.append("******");
		buf.append('@');
		buf.append(getHost()).append(":").append(getPort());
		buf.append('/');
		return buf.toString();
	}

	public String getHost() {
		return host;
	}

	public int getPort() {
		return port;
	}

	public String getPath() {
		return path;
	}

	public Password getAuthentication() {
		return this.auth;
	}

	public String toString() {
		return this.toString(false);
	}

	public String toString(boolean showPassword) {
		return FileNameUtilities.getFullPath(getServer(showPassword), getPath(), '/');
	}

	/**
	 * check if the host & port & auth equal
	 */
	public boolean equals(Object o) {
		if (null == o)
			return false;
		if (this == o)
			return true;
		if (false == o instanceof FTPURL)
			return false;
		FTPURL fu = (FTPURL) o;
		if (fu.port != this.port)
			return false;
		if (false == fu.host.equals(this.host))
			return false;
		if (false == fu.auth.equals(this.auth))
			return false;
		return true;
	}
}
